package pe.com.bbva.pct.dao.impl;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Repository;

import pe.com.bbva.pct.dao.GeneralDAO;

@Repository("GeneralDAO")
public class GeneralDAOImpl<T> implements GeneralDAO<T>{
	
	private static final Logger log = Logger.getLogger(GeneralDAOImpl.class);
	
	protected EntityManager em;
	
	@PersistenceContext
	public void setEntityManager(EntityManager em) {
		this.em = em;		
	}

	@Override
	public void insertarObjeto(T t)throws Exception {		
		em.persist(t);
		em.flush();						
	}
	
	@Override
	public T insertarObjetoReturnId(T t)throws Exception {		
		em.persist(t);
		em.flush();	
		return  t;		
	}

	@Override	
	public T actualizarObjeto(T t) throws Exception{
		T t1 = em.merge(t);
		em.flush();
		return t1;				
	}

	@Override
	public void borrarObjeto(T t) throws Exception{					
		em.remove(t);
		em.flush();			
				
	}

	@Override
	public T obtenerObjeto(Object id, Class<T> type) throws Exception{					
		return em.find(type, id);				
	}

	@Override
	public Object findObjectByNamedQuery(String queryName,Map<String, Object> parameters) throws Exception{					
		return findObjectByNamedQuery(queryName, parameters, 1);		
	}

	@Override
	public Object findObjectByNamedQuery(String queryName,Map<String, Object> parameters, int resultLimit) throws Exception{					
		Query query = em.createNamedQuery(queryName);
		setParameters(query, parameters);
		if (resultLimit > 0) {
		    query.setMaxResults(resultLimit);
		}
		return query.getSingleResult();
	}

	@Override
	public List<T> findByNamedQuery(String queryName) throws Exception{		
		return findByNamedQuery(queryName, 0);			
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> findByNamedQuery(String queryName, int resultLimit) throws Exception {		
		Query query = em.createNamedQuery(queryName);
		if (resultLimit > 0) {
		    query.setMaxResults(resultLimit);
		}
		return query.getResultList();				
	}

	@Override
	public List<T> findByNamedQuery(String queryName,Map<String, Object> parameters) throws Exception{		
		return findByNamedQuery(queryName, parameters, 0);		
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> findByNamedQuery(String queryName,Map<String, Object> parameters, int resultLimit) throws Exception{	
		System.out.println("query :" +queryName);
		Query query = em.createNamedQuery(queryName);
		setParameters(query, parameters);
		if (resultLimit > 0) {
		    query.setMaxResults(resultLimit);
		}
		return (List<T>) query.getResultList();				
	}

	@Override
	public List<Object> findByNativeQuery(String nativeQuery,Map<String, Object> parameters) throws Exception{		
		return findByNativeQuery(nativeQuery, parameters, 0);		
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Object> findByNativeQuery(String nativeQuery,Map<String, Object> parameters, int resultLimit) throws Exception{		
		Query query = em.createQuery(nativeQuery);
		setParameters(query, parameters);
		return query.getResultList();				
	}

	@Override
	public Object findObjectByNativeQuery(String nativeQuery,Map<String, Object> parameters, int resultLimit) throws Exception{		
		Query query=em.createNativeQuery(nativeQuery);
		Iterator<String> it=parameters.keySet().iterator();
		while(it.hasNext()){
		    String key=it.next();
		    query.setParameter(key, parameters.get(key));
		}
		return query.getSingleResult();				
	}

	@Override
	public void executeQueryNative(String sql, Map<String, Object> map) throws Exception{		
		Query query=em.createNativeQuery(sql);
		if(map!=null){	
			setParameters(query,map);
		}
		query.executeUpdate();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Object> executeQueryNativeList(String sql, Map<String, Object> map) throws Exception{		
		Query query=em.createNativeQuery(sql);
		if(map!=null){	
			setParameters(query,map);
		}
		return query.getResultList();				
	}
	
	protected void setParameters(Query query, Map<String, Object> parameters){    				
			for (String key : parameters.keySet()) {			
				if(parameters.get(key)!=null){
					query.setParameter(key, parameters.get(key));
				}
			}							
	}		
}
